const multiparty = require('multiparty')
const { resolve, join } = require('path')
const fs = require('fs')
// const daoUser = require('../dao/daoUser')
module.exports = {
  index(req, resp) {
    // 重新定向
    resp.redirect(301, '/pages/updateFiles.html');
  },
  // 处理上传的文件，并保存到本地
  async updateFiles(req, resp) {
    let username = decodeURIComponent(req.headers['username'])
    // 因为用户名加密后是数字和逗号的组合，如果替换后长度大于1，则表示不是正确的用户名
    let Assertions = username.replaceAll(/[1234567890,]/g, '')
    Assertions.length > 0 ? username = "_myDefault" : (username = username.decode())

    let saveFilesPath = resolve('./', 'src', 'updateFiles', username);
    // 判断文件夹是否存在，不存在则创建
    await DirectoryExistenceAndCreate(saveFilesPath)

    // 生成multiparty对象，并配置上传目标路径
    var form = new multiparty.Form();
    //设置编辑
    form.encoding = 'utf-8';
    //设置文件存储路径
    form.uploadDir = saveFilesPath;
    //上传完成后处理
    form.parse(req, function (err, fields, files) {
      // var filesTmp = JSON.stringify(files, null, 2);
      // console.log('filesTmp:    ' + filesTmp);
      if (err) {
        // console.log('parse error: ' + err);
      } else {
        // console.log('files   ===   ', files)
        var inputFile = files['files[]'][0];
        //重命名为真实文件名
        fs.renameSync(inputFile.path, form.uploadDir + '/' + inputFile.originalFilename, function (err) {
          if (err) {
            console.log('rename error: ' + err);
          } else {
            console.log('rename ok');
          }
        });
      }
      resp.send(JSON.stringify({
        status: 1,
        success: true,
        message: '文件上传成功',
        filename: inputFile.originalFilename
      }, null, 2))
    })
  },
  showFiles(req, resp) {
    let { username } = req.query
    username = decodeURIComponent(username)

    let saveFilesPath = resolve('./', 'src', 'updateFiles', username);
    fs.stat(saveFilesPath, async function (err, stats) {
      if (!stats) { // 路径不存在
        resp.send(JSON.stringify({
          status: 0,
          success: false,
          message: '\n该用户没有缓存的文件。\n\n创建新用户分享给朋友上传文件吧！',
        }, null, 2))
      } else {
        let filesList = getAllFiles(saveFilesPath)
        // console.log('filesList', filesList)
        if (filesList.length == 0) {
          resp.send(JSON.stringify({
            status: 0,
            success: false,
            message: '\n该用户没有缓存的文件。\n\n创建新用户分享给朋友上传文件吧！',
          }, null, 2))
        } else {
          resp.send(JSON.stringify({
            status: 1,
            success: true,
            message: '该用户有缓存的文件。',
            filesList
          }, null, 2))
        }
      }
    });

  },

  // 简单加密一下用户名
  encryptionUsername(req, resp) {
    let { username, message } = req.query
    username = decodeURI(username).encode()
    resp.send(JSON.stringify({
      username,
      message: decodeURI(message)
    }, null, 2))
  }
}

// 定时刷新，每隔1天就删除缓存文件时长超过1天的文件
setInterval(() => {
  console.log('缓存文件开始刷新============',)
  let saveFilesPath = resolve('./', 'src', 'updateFiles');
  let deleteFilesTime = 1000 * 60 * 60 * 24 * 10; // 删除文件和文件夹的时间
  let delete_myDefaultFilesTime = 1000 * 60 * 60 * 24; // 删除_myDefault文件夹的时间
  fileDisplay(saveFilesPath, (obj) => {
    let { folderPath, folderOrFile_s, folderOrFile, real_Path, stats } = obj;
    let tt = new Date().getTime() - new Date(stats.ctime).getTime()
    let filePathList = folderPath.split('\\');
    if (stats.isFile()) {
      // 如果是默认用户，则缓存文件的时长大于1天，则进行删除文件操作，如果是其他用户，则按照传入的时间删除文件
      if (tt - (filePathList[filePathList.length - 1] == '_myDefault' ? delete_myDefaultFilesTime : deleteFilesTime) > 0)
        console.log(`删除 ${real_Path} 文件`),
          fs.rm(real_Path, {
            force: true, recursive: true
          }, (err) => { err && console.log('fs.rm:err:--=- ', real_Path, err) })
    }
    if (stats.isDirectory()) {
      // 如果缓存文件的时长大于规定天数，则进行删除文件夹操作
      if (tt - (deleteFilesTime) > 0)
        console.log(`删除 ${real_Path} 文件夹`),
          // fs.unlink(real_Path, (err) => { console.log('fs.unlink:err== ', real_Path, err); return true })
          fs.rmdir(real_Path, (err) => { err && console.log('fs.unlink:err== ', real_Path, err); return true })
    }
  })
}, 1000 * 60 * 60);


// ===========================================================
// ===========================================================
// ===========================================================

/** 
 * 文件遍历方法 和 删除文件夹及文件 
 * @param folderPath 需要遍历的文件夹路径 
 */
function fileDisplay(folderPath, callback = () => { }) {
  //根据文件路径读取文件，返回文件路径下一级的所有文件及文件夹列表  
  fs.readdir(folderPath, function (err, folderOrFile_s) {
    if (err) console.warn(err)
    else {
      //遍历读取到的文件及文件夹列表  
      folderOrFile_s.forEach(function (folderOrFile) {
        //获取当前文件或文件夹的绝对路径  
        var real_Path = join(folderPath, folderOrFile);
        //根据文件路径获取文件信息，返回一个fs.Stats对象  
        fs.stat(real_Path, function (eror, stats) {
          if (eror) console.warn('获取文件stats失败');
          else {
            if (stats.isDirectory()) fileDisplay(real_Path, callback) //如果是文件夹，就继续遍历该文件夹下面的文件
            callback({
              folderPath, folderOrFile_s, folderOrFile, real_Path, stats
            })
          }
        })
      });
    }
  });
}

// 定义获取文件夹下所有的文件的方法
function getAllFiles(root) {
  var res = [], files = fs.readdirSync(root);
  files.forEach(function (file) {
    var pathname = root + '/' + file
      , stat = fs.lstatSync(pathname);
    if (!stat.isDirectory()) {
      res.push(file);
    } else {
      res = res.concat(getAllFiles(pathname));
    }
  });
  return res
}

//JS字符串加密
String.prototype.encode = function () {
  var bytes = [];
  for (var i = 0; i < this.length; i++) {
    bytes.push(this.charCodeAt(i));
  }
  return bytes.join(',');
}

//JS字符串解密
String.prototype.decode = function () {
  return String.fromCharCode.apply(null, this.trim().split(","));
}

// 传入文件夹的路径看是否存在，存在不用管，不存在则直接创建文件夹
let DirectoryExistenceAndCreate = async function (reaPath) {
  try {
    fs.statSync(reaPath)
  } catch (e) {
    // 不存在文件夹，直接创建 {recursive: true} 这个配置项是配置自动创建多个文件夹
    await fs.promises.mkdir(reaPath, { recursive: true })
  }
}